package cn.iocoder.yudao.module.lowcode.core.magicapi;

import cn.iocoder.yudao.module.lowcode.dal.dataobject.datasource.LowcodeDataSourceConfigDO;
import cn.iocoder.yudao.module.lowcode.service.datasource.LowcodeDataSourceConfigService;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * YuDao Magic API 数据源管理器
 * 
 * 将YuDao的数据源配置集成到Magic API中
 * 
 * @author 芋道源码
 */
@Slf4j
public class YudaoMagicApiDataSourceManager {

    private final LowcodeDataSourceConfigService lowcodeDataSourceConfigService;
    
    /**
     * 数据源缓存
     */
    private final Map<String, DataSource> dataSourceCache = new ConcurrentHashMap<>();

    public YudaoMagicApiDataSourceManager(LowcodeDataSourceConfigService lowcodeDataSourceConfigService) {
        this.lowcodeDataSourceConfigService = lowcodeDataSourceConfigService;
    }

    public DataSource getDataSource(String datasourceName) {
        // 如果是默认数据源，返回null让Magic API使用默认的
        if ("default".equals(datasourceName) || !StringUtils.hasText(datasourceName)) {
            return null;
        }
        
        // 从缓存中获取数据源
        DataSource dataSource = dataSourceCache.get(datasourceName);
        if (dataSource != null) {
            return dataSource;
        }
        
        // 创建新的数据源
        return createDataSource(datasourceName);
    }

    public List<String> datasourceNames() {
        try {
            List<LowcodeDataSourceConfigDO> datasourceConfigs = lowcodeDataSourceConfigService.getEnabledDataSourceConfigList();
            return datasourceConfigs.stream()
                    .map(LowcodeDataSourceConfigDO::getName)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("[YudaoMagicApiDataSourceManager][datasourceNames] 获取数据源名称列表失败", e);
            return Collections.emptyList();
        }
    }

    /**
     * 创建数据源
     */
    private synchronized DataSource createDataSource(String datasourceName) {
        // 双重检查锁定
        DataSource dataSource = dataSourceCache.get(datasourceName);
        if (dataSource != null) {
            return dataSource;
        }
        
        try {
            // 根据名称获取数据源配置  
            LowcodeDataSourceConfigDO config = lowcodeDataSourceConfigService.getDataSourceConfigByName(datasourceName);
            if (config == null) {
                log.warn("[YudaoMagicApiDataSourceManager][createDataSource] 数据源配置不存在: {}", datasourceName);
                return null;
            }
            
            // 创建Druid数据源
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setUrl(config.getUrl());
            druidDataSource.setUsername(config.getUsername());
            druidDataSource.setPassword(config.getPassword());
            druidDataSource.setDriverClassName(config.getDriverClassName());
            
            // 连接池配置
            druidDataSource.setInitialSize(config.getInitialSize() != null ? config.getInitialSize() : 5);
            druidDataSource.setMinIdle(config.getMinIdle() != null ? config.getMinIdle() : 5);
            druidDataSource.setMaxActive(config.getMaxActive() != null ? config.getMaxActive() : 20);
            druidDataSource.setMaxWait(60000);
            druidDataSource.setTimeBetweenEvictionRunsMillis(60000);
            druidDataSource.setMinEvictableIdleTimeMillis(300000);
            druidDataSource.setValidationQuery(config.getTestQuery() != null ? config.getTestQuery() : "SELECT 1");
            druidDataSource.setTestWhileIdle(true);
            druidDataSource.setTestOnBorrow(false);
            druidDataSource.setTestOnReturn(false);
            
            // 初始化数据源
            druidDataSource.init();
            
            // 缓存数据源
            dataSourceCache.put(datasourceName, druidDataSource);
            
            log.info("[YudaoMagicApiDataSourceManager][createDataSource] 创建数据源成功: {}", datasourceName);
            
            return druidDataSource;
            
        } catch (Exception e) {
            log.error("[YudaoMagicApiDataSourceManager][createDataSource] 创建数据源失败: {}", datasourceName, e);
            return null;
        }
    }
    
    /**
     * 移除数据源缓存
     */
    public void evictDataSource(String datasourceName) {
        DataSource dataSource = dataSourceCache.remove(datasourceName);
        if (dataSource instanceof DruidDataSource) {
            DruidDataSource druidDataSource = (DruidDataSource) dataSource;
            try {
                druidDataSource.close();
                log.info("[YudaoMagicApiDataSourceManager][evictDataSource] 移除数据源缓存成功: {}", datasourceName);
            } catch (Exception e) {
                log.error("[YudaoMagicApiDataSourceManager][evictDataSource] 关闭数据源失败: {}", datasourceName, e);
            }
        }
    }
    
    /**
     * 清空所有数据源缓存
     */
    public void evictAllDataSource() {
        for (Map.Entry<String, DataSource> entry : dataSourceCache.entrySet()) {
            if (entry.getValue() instanceof DruidDataSource) {
                DruidDataSource druidDataSource = (DruidDataSource) entry.getValue();
                try {
                    druidDataSource.close();
                } catch (Exception e) {
                    log.error("[YudaoMagicApiDataSourceManager][evictAllDataSource] 关闭数据源失败: {}", entry.getKey(), e);
                }
            }
        }
        dataSourceCache.clear();
        log.info("[YudaoMagicApiDataSourceManager][evictAllDataSource] 清空所有数据源缓存成功");
    }
}